package basicx.oop.lifecyclex

/*-*- coding:utf-8 -*-
* @Author  : ygree 
* @Time    : 2021/6/29 18:58
* @Software : IntelliJ IDEA
*/

class Empty // 空类

// 使用普通函数那样使用构造函数创建类实例：
val site = Empty() // Kotlin 中没有 new 关键字

// 类的属性可以在其声明或主体中列出。
//val 不可变
//var 可变

/**注意：在 JVM 虚拟机中，如果主构造函数的所有参数都有默认值，编译器会生成一个附加的无参的构造函数，这个构造函数会直接使用默认值。
// 这使得 Kotlin 可以更简单的使用像 Jackson 或者 JPA 这样使用无参构造函数来创建类实例的库。*/


private class ConstructDefault(val name: String = "") {

}

private class Construct(val name: String) {

}

private class ConstructNO(name: String) {
}

private class Constructx {
    lateinit var name: String
    private var _name: String = "" // 解决null

    init {
        println("inti")
    }

    constructor(name: String) {
        this.name = name
    }
}
//init->  创建对象的调用顺序先调用的主构造函数->直接代理主函数的构造函数->间接代理主函数的构造函数->调用的构造函数。

private class Constructxx(var name: String) {
    var age: Int = 0
    var sex: Boolean = false

    init {
        println("inti")
    }

    //    两个次构造方法相互委托，会出现错误提示：There is a cycle in the delegation calls chain----委托调用链中有一个循环。
    // 构造重载:代理
    constructor(age: Int) : this("as") {
        println("constructor(age: Int)")
        this.age = age + 1
    }

    constructor(name: String, age: Int) : this(name) {
        println("constructor(name: String, age: Int)")
        this.age = age + 2
    }

    // 3-->1
    constructor(name: String, age: Int, sex: Boolean) : this(age) {
        println("constructor(name: String, age: Int, sex: Boolean)")
        this.name = name
        this.age = age + 3
        this.sex = sex
    }

    //   1 -->3(default)
    constructor(sex: Boolean) : this("name", 10, sex) {
        println("constructor(sex: Boolean)")
        this.sex = sex
    }
}

private class SetGet() {
    /*
    var <propertyName>[: <PropertyType>] [ = <property_initializer>]
    [<getter>]
    [<setter>]
        getter 和 setter 都是可选
        如果属性类型可以从初始化语句或者类的成员函数中推断出来，那就可以省去类型，val不允许设置setter函数，因为它是只读的。
    */
    var name: Int = 0
        private set(name) {
            field = name + 10
        }
        get() {
            return field * 10
        }
    var age: Int = 0
        set(age) {
            field = age + 10
        }
        get() {
            return field * 10
        }

    fun Info() {
        println("${name} ${age}")
    }
}


// 如果一个非抽象类没有声明构造函数(主构造函数或次构造函数)，它会产生一个没有参数的构造函数。
// 构造函数是 public 。如果你不想你的类有公共的构造函数，你就得声明一个空的主构造函数：
class DontCreateMe private constructor()


private fun construct() {
    println("Construct(a).name      ${Construct("a").name}")
    println("ConstructX(a) err:name ${ConstructNO("a")}")
    println("Constructx(a).name     ${Constructx("a").name}")
    println("-=------------")
    println("Constructxx(a) err:name ${Constructxx("a").name}")
    println("-=------------")

    println("Constructxx(a) err:name ${Constructxx("b", 10).name}")
    println("-=------------")

    println("Constructxx(a) err:name ${Constructxx("b", 10, false).name}")
    println("-=------------")

}


private fun setGet() {
    println("-=-----setGet-------")

    val setGet = SetGet()
    println("setGet name ${setGet.name}")
    println("setGet age  ${setGet.age}")
//    setGet.name = 10  //err :private set
    setGet.age = 10
    setGet.Info()
    println("setGet name ${setGet.name}")
    println("setGet age  ${setGet.age}")
    setGet.Info()


}

private  fun main() {
    construct()
    setGet()
}
